﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
using System.Reflection;
using System.Configuration;
using RiaToDalLinq.Contracts;
using RiaToDalLinq.Configuration;
using RiaToDalLinq.Enumeration;

namespace RiaToDalLinq.DalResolvers
{
    /// <summary>
    /// Resolves DAL specific information via configuration settings.
    /// </summary>
    [Export(typeof(IDalResolver))]
    public sealed class ConfigurationDalResolver : IDalResolver
    {
        /// <summary>
        /// Gets a manager instance from an entity name (for example, if we are working with a User entity, it will return a UserManagerInstance).
        /// From there a call such as UserManagerInstance.GetUser(userId) is possible.
        /// </summary>
        /// <param name="entityName"></param>
        /// <returns></returns>
        public object GetManagerInstance(string entityName)
        {
            // ////////////////////////////////////////////////
            // Get configuration
            // ////////////////////////////////////////////////
            RiaToDalLinqConfiguration config = (RiaToDalLinqConfiguration)ConfigurationManager.GetSection("riaToDalLinqSettings");

            // Fully qualified name
            string fullyQualifiedName = config.DalProviderInstance;
            string entityManagerNameFormatString = config.EntityManagerNameFormatString;


            // ////////////////////////////////////////////////
            // End get configuration
            // ////////////////////////////////////////////////

            string[] fullyQualifiedSplit = fullyQualifiedName.Split(',');

            // Get the provider instance name
            string providerInstanceString = fullyQualifiedSplit[0].Trim();

            // Get the assembly name
            string assemblyName = fullyQualifiedSplit[1].Trim();

            // String manip
            int lastDot = providerInstanceString.LastIndexOf('.');
            int length = providerInstanceString.Length;
            string providerInstanceType = providerInstanceString.Substring(0, lastDot);

            // Get the working assembly
            Assembly assembly = (from a in AppDomain.CurrentDomain.GetAssemblies() where a.GetName().Name == assemblyName select a).FirstOrDefault();

            if (assembly == null)
            {
                throw new ApplicationException(string.Format("Assembly {0} could not be found", assemblyName));
            }

            // Get the property name
            string providerPropertyInstanceName = providerInstanceString.Substring(lastDot + 1, length - lastDot - 1);

            //get the type info for the DAL provider
            Type providerType = assembly.GetType(providerInstanceType);

            // Get the instance to the provider
            object instance = providerType.GetProperty(providerPropertyInstanceName).GetValue(null, null);

            //gets a reference to the manager instance on the provider
            PropertyInfo singletonPropertyInfo = providerType.GetProperty(string.Format(entityManagerNameFormatString, entityName));
            object propertyReference = singletonPropertyInfo.GetValue(instance, null);

            // Return the property reference
            return propertyReference;
        }

        public int? GetIdFromCode(Type lookupEntityType, string idFieldName, string codeFieldName, string codeValue)
        {
            return 1;
        }

        public Tuple<string, string> WhereClauseParameter
        {
            get
            {
                return new Tuple<string, string>("whereClause", string.Empty);
            }
        }

        public Tuple<string, string> OrderByParameter
        {
            get
            {
                return new Tuple<string, string>("orderBy", string.Empty);
            }
        }

        public Tuple<string, int> PageStartParameter
        {
            get
            {
                return new Tuple<string, int>("pageIndex", 0);
            }
        }

        public Tuple<string, int> PageSizeParameter
        {
            get
            {
                return new Tuple<string, int>("pageSize", 25);
            }
        }

        public Tuple<string, int> RowCountParameter
        {
            get
            {
                return new Tuple<string, int>("rowCount", 0);
            }
        }

        public PageStartActAs PageStartActingAs
        {
            get
            {
                return Enumeration.PageStartActAs.PageIndex;
            }
        }
    }
}
